package com.myproject.myblogserver.controller;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.myproject.myblogserver.contant.CommonConstants;
import com.myproject.myblogserver.converter.BlogDtoConverter;
import com.myproject.myblogserver.dto.FileUploadResultDto;
import com.myproject.myblogserver.dto.PageResultDto;
import com.myproject.myblogserver.dto.blog.BlogPreviewDto;
import com.myproject.myblogserver.dto.blog.BlogUploadDto;
import com.myproject.myblogserver.dto.search.BlogSearchDto;
import com.myproject.myblogserver.entity.Blog;
import com.myproject.myblogserver.entity.BlogLike;
import com.myproject.myblogserver.entity.BlogTag;
import com.myproject.myblogserver.entity.FavoriteFolder;
import com.myproject.myblogserver.entity.FolderBlog;
import com.myproject.myblogserver.entity.User;
import com.myproject.myblogserver.service.IMyBlogPreviewService;
import com.myproject.myblogserver.service.IUserService;
import com.myproject.myblogserver.service.IBlogLikeService;
import com.myproject.myblogserver.service.IBlogService;
import com.myproject.myblogserver.service.IBlogTagService;
import com.myproject.myblogserver.service.IFavoriteFolderService;
import com.myproject.myblogserver.service.IFolderBlogService;
import com.myproject.myblogserver.utils.ApiResponse;
import com.myproject.myblogserver.utils.JwtUtil;
import com.myproject.myblogserver.utils.TokenUtil;

/**
 * <p>
 * 博客表 前端控制器
 * </p>
 *
 * @author jiangweike
 * @since 2025-01-12
 */
@RestController
@RequestMapping("/blog")
public class BlogController {

    @Value("${web.upload-path}")
    private String uploadPath;

    @Autowired
    private IBlogService blogService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IBlogLikeService blogLikeService;

    @Autowired
    private IMyBlogPreviewService blogPreviewService;

    @Autowired
    private IBlogTagService blogTagService;

    @Autowired
    private IFolderBlogService folderBlogService;

    @Autowired
    private IFavoriteFolderService favoriteFolderService;

    @PostMapping("/create")
    public ResponseEntity<?> create(@RequestBody BlogUploadDto blogUploadDto,
            @RequestHeader("Authorization") String authHeader) {
        var savedBlog = blogService.saveBlog(blogUploadDto, TokenUtil.getUserIdFromToken(authHeader));
        if (savedBlog != null)
            return ResponseEntity.ok("上传成功！");
        else
            return ResponseEntity.badRequest().body("上传失败！");
    }

    @GetMapping("/get/{blogId}")
    public ResponseEntity<?> get(@PathVariable Long blogId,
            @RequestHeader("Authorization") String authHeader) {
        var userId = JwtUtil.extractUserIdFromAuthHeader(authHeader);
        var blog = blogService.lambdaQuery().eq(Blog::getId, blogId)
                .eq(Blog::getIsDeleted, CommonConstants.DELETED_STATUS_NO)
                .select(Blog::getId, Blog::getTitle, Blog::getSummary, Blog::getContent, Blog::getAuthorId,
                        Blog::getCreatedAt)
                .one();
        if (blog == null)
            return ResponseEntity.badRequest().body("获取失败！");

        var tags = blogTagService.lambdaQuery().eq(BlogTag::getBlogId, blogId)
                .eq(BlogTag::getIsDeleted, CommonConstants.DELETED_STATUS_NO)
                .select(BlogTag::getTagName).list();
        var blogShowDto = BlogDtoConverter.convertToBlogShowDto(blog, tags);

        var user = userService.lambdaQuery()
                .eq(User::getIsDeleted, CommonConstants.DELETED_STATUS_NO)
                .eq(User::getId, blog.getAuthorId())
                .select(User::getName)
                .one();
        blogShowDto.setUserName(user.getName());

        var isLike = blogLikeService.lambdaQuery()
                .eq(BlogLike::getIsDeleted, CommonConstants.DELETED_STATUS_NO)
                .eq(BlogLike::getBlogId, blog.getId())
                .eq(BlogLike::getUserId, userId)
                .exists();
        blogShowDto.setIsLike(isLike);

        var likeCount = blogLikeService.lambdaQuery()
                .eq(BlogLike::getIsDeleted, CommonConstants.DELETED_STATUS_NO)
                .eq(BlogLike::getBlogId, blog.getId())
                .count();
        blogShowDto.setLikeCount(likeCount);

        var folderBlog = folderBlogService.lambdaQuery()
                .eq(FolderBlog::getIsDeleted, CommonConstants.DELETED_STATUS_NO)
                .eq(FolderBlog::getBlogId, blog.getId())
                .select(FolderBlog::getFolderId)
                .one();
                
        if (folderBlog != null) {
            var isFolder = favoriteFolderService.lambdaQuery()
                    .eq(FavoriteFolder::getIsDeleted, CommonConstants.DELETED_STATUS_NO)
                    .eq(FavoriteFolder::getUserId, userId)
                    .eq(FavoriteFolder::getId, folderBlog.getId())
                    .exists();
            blogShowDto.setIsFavorited(isFolder);
        }

        return ResponseEntity.ok().body(blogShowDto);
    }

    @GetMapping("/getPreview/{pageIndex}")
    public ResponseEntity<?> getPreview(@PathVariable Integer pageIndex,
            @RequestHeader("Authorization") String authHeader) {
        var blogPreviewPageResultDto = blogPreviewService.getPageResultBlogPreview(pageIndex);
        if (blogPreviewPageResultDto != null && blogPreviewPageResultDto.getContent() != null)
            return ResponseEntity.ok().body(blogPreviewPageResultDto);
        else
            return ResponseEntity.badRequest().body("获取失败！");
    }

    /**
     * 搜索
     * 范围：作者名，博客名，博客摘要，博客正文，标签
     * 
     * @param keyword
     * @param authHeader
     * @return
     */
    @PostMapping("/getSearch")
    public ResponseEntity<?> getSearch(@RequestBody BlogSearchDto blogSearchDto,
            @RequestHeader("Authorization") String authHeader) {
        var blogPreviewPage = blogService.searchBlogs(blogSearchDto.getKeywordList(),
                new Page<>(blogSearchDto.getPageIndex(), CommonConstants.DEFAULT_PAGE_SIZE));
        if (blogPreviewPage.getRecords() != null){
            var blogPreviewPageResultDto=new PageResultDto<BlogPreviewDto>();
            blogPreviewPageResultDto.setContent(blogPreviewPage.getRecords());
            blogPreviewPageResultDto.setTotalPages(blogPreviewPage.getPages());
            return ResponseEntity.ok().body(blogPreviewPageResultDto);
        }
            
        else
            return ResponseEntity.badRequest().body("获取失败！");
    }

    @PostMapping("/uploadFile")
    public ResponseEntity<?> uploadFile(@RequestParam MultipartFile[] files) { // 支持多文件上传
        FileUploadResultDto result = new FileUploadResultDto();

        try {
            Path uploadDir = Paths.get(uploadPath);
            Files.createDirectories(uploadDir);

            for (MultipartFile file : files) {
                if (file.isEmpty()) {
                    result.addErrorFile(file.getOriginalFilename());
                    continue;
                }

                try {
                    String originalName = file.getOriginalFilename();
                    String extension = originalName != null && originalName.contains(".")
                            ? originalName.substring(originalName.lastIndexOf("."))
                            : "unknown";
                    String uniqueName = UUID.randomUUID() + extension;

                    Path target = uploadDir.resolve(uniqueName);
                    Files.copy(file.getInputStream(), target, StandardCopyOption.REPLACE_EXISTING);

                    result.addSuccessFile(originalName, "http://127.0.0.1:8080/files/" + uniqueName);
                } catch (IOException e) {
                    result.addErrorFile(file.getOriginalFilename());
                }
            }

            return ResponseEntity.ok(ApiResponse.success(result));
        } catch (IOException e) {
            return ResponseEntity.status(500)
                    .body(ApiResponse.error(500, "服务器错误：" + e.getMessage()));
        }
    }
}
